function hfile = cmp_AddComponent(hfile, cmap)
% CMP::AddComponent  - add a component to a CMP/ICA file
%
% FORMAT:       cmp.AddComponent([cmap]);
%
% Input fields:
%
%       cmap        1x1 struct with optional fields (as in Component)
%        .Type               component type (1, ...)
%        .LowerThreshhold    lower threshold (default: 0)
%        .UpperThreshhold    upper threshold (default: 1)
%        .Name               component name (default: 'component %d')
%        .RGBLowerThreshPos  RGB color code for positive lower thresh
%        .RGBUpperThreshPos  RGB color code for positive upper thresh
%        .RGBLowerThreshNeg  RGB color code for negative lower thresh
%        .RGBUpperThreshNeg  RGB color code for negative upper thresh
%        .UseRGBColor        whether or not use CMP color (default: 1)
%        .TransColorFactor   transparent coloring factor (default: 1)
%        .TimePointData      timecourse (default: zeros(NrOfTimePoints,1))
%        .CMPData            XxYxZ component map (dims must match)
%                   additionally the parameter values can be given in
%        .ParamValues        values will go into .ComponentParameters
%
% No output fields.
%
% Note: if no input argument is given, the dimensions will be taken
%       from the main structure

% Version:  v0.7b
% Build:    7083008
% Date:     Aug-30 2007, 8:57 AM CEST
% Author:   Jochen Weber, Brain Innovation, B.V., Maastricht, NL
% URL/Info: http://wiki.brainvoyager.com/BVQXtools

% only valid for single file
if nargin < 1 || ...
    numel(hfile) ~= 1 || ...
   ~isBVQXfile(hfile, 'cmp')
    error( ...
        'BVQXfile:BadArgument', ...
        'Invalid call to %s.', ...
        mfilename ...
    );
end

% get current X, Y, Z dims
bc = bvqxfile_getcont(hfile.L);
pres = bc.Resolution;
dimx = (bc.XEnd - bc.XStart) / pres;
dimy = (bc.YEnd - bc.YStart) / pres;
dimz = (bc.ZEnd - bc.ZStart) / pres;

% no component struct
if nargin < 2 || ...
   ~isstruct(cmap) || ...
    isempty(cmap)
    cmap = struct('CMPData', zeros([dimx, dimy, dimz]));

% no or non numeric CMPData
elseif ~isfield(cmap, 'CMPData') || ...
   ~isnumeric(cmap.CMPData)
    cmap.CMPData = zeros([dimx, dimy, dimz]);
    
% check CMPData size
elseif numel(size(cmap.CMPData)) ~= 3 || ...
    any(size(cmap.CMPData) ~= [dimx, dimy, dimz])
    error( ...
        'BVQXfile:BadArgument', ...
        'Bad dimension of ComponentMap.' ...
    );
end

% is this the first component?
nc = numel(bc.Component);
if nc < 1
    defvals = struct( ...
        'Type'             , 1, ...
        'LowerThreshold'   , 2.5, ...
        'UpperThreshold'   , 8, ...
        'Name'             , 'component 1', ...
        'RGBLowerThreshPos', [255,   0,   0], ...
        'RGBUpperThreshPos', [255, 192,   0], ...
        'RGBLowerThreshNeg', [  0,   0, 128], ...
        'RGBUpperThreshNeg', [  0, 128, 255], ...
        'UseRGBColor'      , 1, ...
        'TransColorFactor' , 1, ...
        'TimePointData'    , zeros(bc.NrOfTimePoints, 1), ...
        'ParamValues'      , zeros(1, bc.NrOfComponentParameters));

% adding another component
else
    defvals = bc.Component(1);
    defvals.Name = 'component %d';
    defvals.TimePointData = zeros(bc.NrOfTimePoints, 1);
    defvals.ParamValues = zeros(1, bc.NrOfComponentParameters);
end

% add missing fields to struct
mfields = fieldnames(defvals);
for fc = 1:numel(mfields)
    if ~isfield(cmap, mfields{fc})
        for cc = 1:numel(cmap)
            cmap(cc).(mfields{fc}) = defvals.(mfields{fc});
        end
    end
end

% add component(s)
for cc = 1:numel(cmap)
    
    % increase counter
    nc = nc + 1;
    
    % make settings
    bc.Component(nc).Type              = cmap(cc).Type;
    bc.Component(nc).LowerThreshold    = cmap(cc).LowerThreshold;
    bc.Component(nc).UpperThreshold    = cmap(cc).UpperThreshold;
    if sum(cmap(cc).Name == '%') ~= 1
        bc.Component(nc).Name          = cmap(cc).Name;
    else
        bc.Component(nc).Name = sprintf(cmap(cc).Name, nc);
    end
    bc.Component(nc).RGBLowerThreshPos = cmap(cc).RGBLowerThreshPos;
    bc.Component(nc).RGBUpperThreshPos = cmap(cc).RGBUpperThreshPos;
    bc.Component(nc).RGBLowerThreshNeg = cmap(cc).RGBLowerThreshNeg;
    bc.Component(nc).RGBUpperThreshNeg = cmap(cc).RGBUpperThreshNeg;
    bc.Component(nc).UseRGBColor       = cmap(cc).UseRGBColor;
    bc.Component(nc).TransColorFactor  = cmap(cc).TransColorFactor;
    bc.Component(nc).TimePointData     = cmap(cc).TimePointData;
    
    % set CMPData
    bc.Component(nc).CMPData = cmap.CMPData;
    
    % set ParameterValue
    for pc = 1:numel(cmap(cc).ParamValues)
        bc.ComponentParameter(pc).Values(nc) = ...
            cmap.ParamValues(pc);
    end
end

% set correct number
bc.NrOfComponents = nc;
bc.NrOfComponentParameters = numel(bc.ComponentParameter);

% set into storage
bvqxfile_setcont(hfile.L, bc);
